package com.example.oldguy.modules.app.controllers;


import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Controller
@RequestMapping(value = "expense")
public class ExpenseController {

    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;


    @Autowired
    private ProcessEngine processEngine;





    @RequestMapping(value = "addMap",method= RequestMethod.POST )
    @ResponseBody
    public String addMap(String userId, @RequestParam(required = false) Map  map) {
        for (Object key : map.keySet()) {
            System.out.println("key= "+ key + " and value= " + map.get(key));
        }
        System.out.println(userId+"用户ID");
        return "收到";
    }


    /**
     * 添加报销
     *
     * @param userId    用户Id
     * @param money     报销金额
     * @param descption 描述
     */
    @RequestMapping(value = "add")
    @ResponseBody
    public String addExpense(String userId, Integer money, String descption) {
        try {
            //启动流程
            HashMap<String, Object> map = new HashMap<>();
            map.put("user", userId);
//            runtimeService.startProcessInstanceById()
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ccgzl", map);
            return "提交成功.流程Id为：" + processInstance.getId();
        }catch (Exception e){
            e.printStackTrace();
        }
        return "aaaaaa ";
    }


    /**
     * 获取审批管理列表
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(String userId) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().list();
        for (Task task : tasks) {
            System.out.println(task.toString());
            //processInstanceId  流程图ID  APP_TEST_ENTITY
        }
        return tasks.toString();
    }
    /**
     * 批准
     *
     * @param taskId 任务ID
     */
    @RequestMapping(value = "apply")
    @ResponseBody
    public String apply(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new RuntimeException("流程不存在");
        }
        //通过审核
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "通过");
        map.put("user", "25");
        taskService.complete(taskId, map);
        return "processed ok!";
    }

    /**
     * 拒绝
     */
    @ResponseBody
    @RequestMapping(value = "reject")
    public String reject(String taskId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("outcome", "驳回");
        taskService.complete(taskId, map);
        return "reject";
    }

    /**
     * 生成流程图
     *
     * @param processId 任务ID
     */
    @RequestMapping(value = "processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();

        //流程走完的不显示图
        if (pi == null) {
            return;
        }
        Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        String InstanceId = task.getProcessInstanceId();
        List<Execution> executions = runtimeService
                .createExecutionQuery()
                .processInstanceId(InstanceId)
                .list();

        //得到正在执行的Activity的Id
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in =diagramGenerator.generateDiagram
                (bpmnModel, "png", activityIds, flows, engconf.getActivityFontName()+"",
                        engconf.getLabelFontName()+"", engconf.getAnnotationFontName()+"",
                        engconf.getClassLoader(), 1.0,true);

        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            httpServletResponse.setCharacterEncoding("UTF-8");

            //2.直接规定浏览器看这份数据的时候，使用什么编码来看。
//            httpServletResponse.setHeader("Content-Type", "text/html; charset=UTF-8");
//            httpServletResponse.setContentType("text/plain;charset=UTF-8");
            httpServletResponse.setContentType("text/html");
            out = httpServletResponse.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 任务历史
     *
     * @param processId 部署id
     */
    @RequestMapping(value = "getHistoryProcess")
    public List<HistoricActivityInstance> getHistoryProcess(String processId) {
        List<HistoricActivityInstance> list = historyService // 历史相关Service
                .createHistoricActivityInstanceQuery() // 创建历史活动实例查询
                .processInstanceId(processId) // 执行流程实例id
                .finished()
                .list();
        return list;
    }

//    /**
//     * 生成流程图
//     *
//     * @param processId 任务ID
//     */
//    @RequestMapping(value = "processDiagram1")
//    public void genProcessDiagram1(HttpServletResponse httpServletResponse, String processId) throws Exception {
//        //1.获取当前的流程实例
//        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
//        String processDefinitionId = null;
//        List<String> activeActivityIds = null;
//        //2.获取所有的历史轨迹对象
//        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
//                .processInstanceId(processId).list();
//        Map<String, HistoricActivityInstance> hisActivityMap = new HashMap<>();
//        list.forEach(historicActivityInstance -> {
//            if (!hisActivityMap.containsKey(historicActivityInstance.getActivityId())) {
//                hisActivityMap.put(historicActivityInstance.getActivityId(), historicActivityInstance);
//            }
//        });
//        //3. 获取流程定义id和高亮的节点id
//        if (processInstance != null) {
//            //3.1. 正在运行的流程实例
//            processDefinitionId = processInstance.getProcessDefinitionId();
//            activeActivityIds = runtimeService.getActiveActivityIds(processId);
//        } else {
//            //3.2. 已经结束的流程实例
//            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
//            processDefinitionId = historicProcessInstance.getProcessDefinitionId();
//            activeActivityIds = new ArrayList<>();
//            List<EndEvent> endEvents = bpmnModelService.findEndFlowElement(processDefinitionId);
//            List<String> finalActiveActivityIds = activeActivityIds;
//            endEvents.forEach(endEvent -> {
//                if (hisActivityMap.containsKey(endEvent.getId())) {
//                    finalActiveActivityIds.add(endEvent.getId());
//                }
//            });
//        }
//        //4. 获取流程定义的所有节点信息
//        List<FlowNode> flowNodes = bpmnModelService.findFlowNodes(processDefinitionId);
//        Map<String, FlowNode> activityMap = flowNodes.stream().collect(Collectors.toMap(FlowNode::getId, flowNode -> flowNode));
//        List<String> highLightedFlows = new ArrayList<>();
//        //5. 递归得到高亮线
//        activeActivityIds.forEach(activeActivityId -> this.getHighLightedFlows(activityMap, hisActivityMap, activeActivityId, highLightedFlows, activeActivityId));
//        //6. 获取bpmnModel对象
//        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//        //7. 生成图片流
//        InputStream in = flowProcessDiagramGenerator.generateDiagram(bpmnModel, activeActivityIds, highLightedFlows);
//        OutputStream out = null;
//        byte[] buf = new byte[1024];
//        int legth = 0;
//        try {
//            httpServletResponse.setCharacterEncoding("UTF-8");
//
//            //2.直接规定浏览器看这份数据的时候，使用什么编码来看。
////            httpServletResponse.setHeader("Content-Type", "text/html; charset=UTF-8");
////            httpServletResponse.setContentType("text/plain;charset=UTF-8");
//            httpServletResponse.setContentType("text/html");
//            out = httpServletResponse.getOutputStream();
//            while ((legth = in.read(buf)) != -1) {
//                out.write(buf, 0, legth);
//            }
//        } finally {
//            if (in != null) {
//                in.close();
//            }
//            if (out != null) {
//                out.close();
//            }
//        }
//    }

}
